{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Common Operations"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## What common operations are supported?"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Just normal mappers:\n",
    "\n",
    "* Evaluation\n",
    "* Turning expressions into 'human-readable' strings\n",
    "* Performing substitution\n",
    "* Taking derivatives\n",
    "* Finding variables on which an expression depends\n",
    "* Code Generation\n",
    "\n",
    "Also:\n",
    "\n",
    "* Parsing (i.e. turning a string into an expression)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Evaluation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Power(Sum((Power(Variable('x'), 2), Power(Variable('y'), 2))), 0.5)"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from pymbolic import parse\n",
    "from pymbolic.mapper.evaluator import EvaluationMapper\n",
    "\n",
    "expr = parse(\"(x**2 + y**2)**0.5\")\n",
    "expr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(x**2 + y**2)**0.5\n"
     ]
    }
   ],
   "source": [
    "#clear\n",
    "print(expr)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "17.26267650163207\n"
     ]
    }
   ],
   "source": [
    "#clear\n",
    "evm = EvaluationMapper({\"x\": 17, \"y\": 3})\n",
    "\n",
    "print(evm(expr))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This is just a normal mapper, so its behavior can be overridden as described before."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Finding Independent Variables"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{Variable('x'), Variable('y')}"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from pymbolic.mapper.dependency import DependencyMapper\n",
    "\n",
    "depmap = DependencyMapper()\n",
    "depmap(expr)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Code generation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'pow(x + 4, 17)'"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from pymbolic.mapper.c_code import CCodeMapper\n",
    "\n",
    "ccm = CCodeMapper()\n",
    "x = parse(\"x\")\n",
    "ccm((x+4)**17)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "(We're using `parse` here just to give us a `Variable(\"x\")` object.)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Common subexpressions"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Often, some parts of an expression occur multiple times in a bigger expression."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'pow(x + 4, 3) + 4 * pow(x + 4, 3) * h * h + 2 * pow(x + 4, 3) * h'"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "u = (x+4)**3\n",
    "\n",
    "h = parse(\"h\")\n",
    "\n",
    "expr = u + 2*u*h + 4*u*h**2\n",
    "ccm(expr)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Obviously, that doesn't lead to great code. In particular, the redundancy is carried through to the code side.\n",
    "\n",
    "There is a mechanism to prevent this redundancy. Individual parts of an expression can be tagged as \"common subexpressions\"."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "_cse0 = pow(x + 4, 3)\n",
      "_cse0 + 4 * _cse0 * h * h + 2 * _cse0 * h\n"
     ]
    }
   ],
   "source": [
    "from pymbolic.primitives import CommonSubexpression as CSE\n",
    "\n",
    "u = CSE((x+4)**3)\n",
    "\n",
    "h = parse(\"h\")\n",
    "\n",
    "expr = u + 2*u*h + 4*u*h**2\n",
    "\n",
    "result = ccm(expr)\n",
    "\n",
    "for name, value in ccm.cse_name_list:\n",
    "    print(name, \"=\", value)\n",
    "    \n",
    "print(result)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "(These names can be customized, in case you're wondering.)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.5.0+"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
